/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.beaninfo.editors; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.*; import java.util.Collections; import java.util.Vector; import java.util.Enumeration; import java.util.ResourceBundle; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; import javax.swing.colorchooser.AbstractColorChooserPanel; import javax.swing.colorchooser.ColorSelectionModel; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; /** A property editor for Color class. * (Final only for performance, can be unfinaled if desired) * * @author Jan Jancura, Ian Formanek */ public final class ColorEditor implements PropertyEditor, org.openide.explorer.propertysheet.editors.XMLPropertyEditor { // static ..................................................................................... // the bundle to use static ResourceBundle bundle = NbBundle.getBundle (ColorEditor.class); private static JColorChooser staticChooser; public static final int AWT_PALETTE = 1; public static final int SYSTEM_PALETTE = 2; public static final int SWING_PALETTE = 3; private static final String awtColorNames[] = { "white", "lightGray", "gray", "darkGray", "black", // NOI18N "red", "pink", "orange", "yellow", "green", "magenta", // NOI18N "cyan", "blue" }; // NOI18N private static final Color awtColors[] = { Color.white, Color.lightGray, Color.gray, Color.darkGray, Color.black, Color.red, Color.pink, Color.orange, Color.yellow, Color.green, Color.magenta, Color.cyan, Color.blue }; private static final String systemColorNames[] = { "Active Caption", "Active Caption Border", // NOI18N "Active Caption Text", "Control", "Control Dk Shadow", // NOI18N "Control Highlight", "Control Lt Highlight", // NOI18N "Control Shadow", "Control Text", "Desktop", // NOI18N "Inactive Caption", "Inactive Caption Border", // NOI18N "Inactive Caption Text", "Info", "Info Text", "Menu", // NOI18N "Menu Text", "Scrollbar", "Text", "Text Highlight", // NOI18N "Text Highlight Text", "Text Inactive Text", "Text Text", // NOI18N "Window", "Window Border", "Window Text"}; // NOI18N private static final String systemGenerate[] = { "activeCaption", "activeCaptionBorder", // NOI18N "activeCaptionText", "control", "controlDkShadow", // NOI18N "controlHighlight", "controlLtHighlight", // NOI18N "controlShadow", "controlText", "desktop", // NOI18N "inactiveCaption", "inactiveCaptionBorder", // NOI18N "inactiveCaptionText", "info", "infoText", "menu", // NOI18N "menuText", "scrollbar", "text", "textHighlight", // NOI18N "textHighlightText", "textInactiveText", "textText", // NOI18N "window", "windowBorder", "windowText"}; // NOI18N private static final Color systemColors[] = { SystemColor.activeCaption, SystemColor.activeCaptionBorder, SystemColor.activeCaptionText, SystemColor.control, SystemColor.controlDkShadow, SystemColor.controlHighlight, SystemColor.controlLtHighlight, SystemColor.controlShadow, SystemColor.controlText, SystemColor.desktop, SystemColor.inactiveCaption, SystemColor.inactiveCaptionBorder, SystemColor.inactiveCaptionText, SystemColor.info, SystemColor.infoText, SystemColor.menu, SystemColor.menuText, SystemColor.scrollbar, SystemColor.text, SystemColor.textHighlight, SystemColor.textHighlightText, SystemColor.textInactiveText, SystemColor.textText, SystemColor.window, SystemColor.windowBorder, SystemColor.windowText}; /** Swing colors names and values are static and lazy initialized. * They are also cleared when l&f changes. */ private static String swingColorNames[]; private static Color swingColors[]; static { UIManager.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { swingColorNames = null; swingColors = null; } }); swingColorNames = null; swingColors = null; } // variables .................................................................................. public int palette = AWT_PALETTE; private SuperColor color; private PropertyChangeSupport support; public static JColorChooser getStaticChooser () { if (staticChooser == null) { staticChooser = new JColorChooser () { public void setColor (Color c) { if (c == null) return; super.setColor (c); } }; staticChooser.addChooserPanel ( new NbColorChooserPanel (AWT_PALETTE, awtColorNames, awtColors, bundle.getString ("CTL_AWTPalette")) ); initSwingConstants(); staticChooser.addChooserPanel ( new NbColorChooserPanel (SWING_PALETTE, swingColorNames, swingColors, bundle.getString ("CTL_SwingPalette")) ); staticChooser.addChooserPanel ( new NbColorChooserPanel (SYSTEM_PALETTE, systemColorNames, systemColors, bundle.getString ("CTL_SystemPalette")) ); } return staticChooser; } // init ....................................................................................... public ColorEditor() { support = new PropertyChangeSupport (this); } // main methods ....................................................................................... public Object getValue () { return color; } public void setValue (Object object) { if (object != null) { if (!(object instanceof Color)) throw new IllegalArgumentException (object.toString ()); if (object instanceof SuperColor) color = (SuperColor) object; else color = new SuperColor ((Color) object); } support.firePropertyChange ("", null, null); // NOI18N } public String getAsText () { if (color == null) return "null"; // NOI18N return color.getAsText (); } public void setAsText (String string) throws IllegalArgumentException { int i1 = string.indexOf (44); int j1 = string.indexOf (44, i1 + 1); try { if (i1 < 0 || j1 < 0) throw new Exception (); int k = Integer.parseInt (string.substring (0, i1)); int i2 = Integer.parseInt (string.substring (i1 + 1, j1)); int j2 = Integer.parseInt (string.substring (j1 + 1)); setValue (new SuperColor (null, 0, new Color (k, i2, j2))); } catch (Exception e) { int i; switch (palette) { default: case AWT_PALETTE: i = getIndex (awtColorNames, string); if (i < 0) break; setValue (new SuperColor (string, AWT_PALETTE, awtColors [i])); return; case SYSTEM_PALETTE: i = getIndex (systemColorNames, string); if (i < 0) break; setValue (new SuperColor (string, SYSTEM_PALETTE, systemColors [i])); return; case SWING_PALETTE: initSwingConstants(); i = getIndex (swingColorNames, string); if (i < 0) break; setValue (new SuperColor (string, SWING_PALETTE, swingColors [i])); return; }; throw new IllegalArgumentException (string); } return; } public String getJavaInitializationString () { if (color == null) return "null"; // NOI18N if (color.getID () == null) return "new java.awt.Color (" + color.getRed () + ", " + color.getGreen () + // NOI18N ", " + color.getBlue () + ")"; // NOI18N switch (color.getPalette ()) { default: case AWT_PALETTE: return "java.awt.Color." + color.getID (); // NOI18N case SYSTEM_PALETTE: return "java.awt.SystemColor." + systemGenerate [getIndex (systemColorNames, color.getID ())]; // NOI18N case SWING_PALETTE: initSwingConstants(); int i = getIndex (swingColorNames, color.getID ()); if (i < 0) return "new java.awt.Color (" + color.getRed () + ", " + color.getGreen () + // NOI18N ", " + color.getBlue () + ")"; // NOI18N return "(java.awt.Color) javax.swing.UIManager.getDefaults ().get (\"" + // NOI18N color.getID () + "\")"; // NOI18N } } public String[] getTags () { switch (palette) { case AWT_PALETTE: return awtColorNames; case SYSTEM_PALETTE: return systemColorNames; case SWING_PALETTE: initSwingConstants(); return swingColorNames; default: return awtColorNames; } } public boolean isPaintable () { return true; } public void paintValue (Graphics g, Rectangle rectangle) { Color color = g.getColor (); if (this.color != null) { g.setColor (Color.black); g.drawRect (rectangle.x + 6, rectangle.y + rectangle.height / 2 - 5 , 10, 10); g.setColor (this.color); g.fillRect (rectangle.x + 7, rectangle.y + rectangle.height / 2 - 4 , 9, 9); } g.setColor (Color.black); FontMetrics fm = g.getFontMetrics (); g.drawString (getAsText (), rectangle.x + 22, rectangle.y + (rectangle.height - fm.getHeight ()) / 2 + fm.getAscent ()); g.setColor (color); } public boolean supportsCustomEditor () { return true; } public Component getCustomEditor () { return new NbColorChooser (this, getStaticChooser ()); } public void addPropertyChangeListener (PropertyChangeListener propertyChangeListener) { support.addPropertyChangeListener (propertyChangeListener); } public void removePropertyChangeListener (PropertyChangeListener propertyChangeListener) { support.removePropertyChangeListener (propertyChangeListener); } // helper methods ....................................................................................... static int getIndex (Object[] names, Object name) { int i, k = names.length; for (i = 0; i < k; i++) if (names [i].equals (name)) return i; return -1; } static void initSwingConstants() { if (swingColorNames != null) return; UIDefaults def = UIManager.getDefaults (); Enumeration e = def.keys (); Vector names = new Vector (); while (e.hasMoreElements ()) { Object k = e.nextElement (); if (! (k instanceof String)) continue; Object v = def.get (k); if (! (v instanceof Color)) continue; names.addElement ((String)k); } Collections.sort (names); swingColorNames = new String [names.size ()]; names.copyInto (swingColorNames); // QuickSorter.STRING.sort (swingColorNames); swingColors = new Color [swingColorNames.length]; int i, k = swingColorNames.length; for (i = 0; i < k; i++) swingColors [i] = (Color) def.get (swingColorNames [i]); } // innerclasses ............................................................................................ static class NbColorChooser extends JPanel implements ChangeListener { /** Color property editor */ final ColorEditor editor; /** Color chooser instance */ final JColorChooser chooser; /** Reference to model which holds the color selected in the color chooser */ final ColorSelectionModel selectionModel; static final long serialVersionUID =-6230228701104365037L; public NbColorChooser (final ColorEditor editor, final JColorChooser chooser) { this.editor = editor; this.chooser = chooser; selectionModel = chooser.getSelectionModel(); setLayout (new BorderLayout ()); add (chooser, BorderLayout.CENTER); chooser.setColor ((Color)editor.getValue ()); selectionModel.addChangeListener (this); HelpCtx.setHelpIDString (this, NbColorChooser.class.getName ()); } public void removeNotify () { selectionModel.removeChangeListener (this); } public Dimension getPreferredSize () { Dimension s = super.getPreferredSize (); return new Dimension (s.width + 50, s.height + 10); } /*** implementation of the ChangeListener interface */ public void stateChanged (ChangeEvent evt) { editor.setValue(selectionModel.getSelectedColor()); } } static class SuperColor extends Color { /** generated Serialized Version UID */ static final long serialVersionUID = 6147637669184334151L; private String id = null; private int palette = 0; SuperColor (Color color) { super (color.getRed (), color.getGreen (), color.getBlue ()); int i = getIndex (ColorEditor.awtColors, color); if (i < 0) return; id = awtColorNames [i]; } SuperColor (String id, int palette, Color color) { super (color.getRed (), color.getGreen (), color.getBlue ()); this.id = id; this.palette = palette; } String getID () { return id; } int getPalette () { return palette; } String getAsText () { if (id != null) return id; return "[" + getRed () + "," + getGreen () + "," + getBlue () + "]"; // NOI18N } } /** Color chooser panel which can be added into JColorChooser */ static final class NbColorChooserPanel extends AbstractColorChooserPanel implements ListSelectionListener { /** generated Serialized Version UID */ static final long serialVersionUID = -2792992315444428631L; /** List holding palette colors */ JList list; String [] names; Color [] colors; Color color; int palette; /** Name for display of this chooser panel */ String displayName; /** Constructs our chooser panel with specified * palette, names and colors to be shown in the list */ NbColorChooserPanel (final int palette, final String[] names, final Color[] colors, final String displayName) { this.names = names; this.colors = colors; this.palette = palette; this.displayName = displayName; } /** Builds - creates a chooser */ protected void buildChooser () { setLayout (new BorderLayout ()); add (BorderLayout.CENTER, new JScrollPane (list = new JList (names))); list.setCellRenderer (new MyListCellRenderer ()); list.addListSelectionListener (this); } /** Get called when state of selected color changes */ public void updateChooser () { Color c = color; if ((c instanceof SuperColor) && (palette == ((SuperColor)c).getPalette ())) { int i = getIndex (names, ((SuperColor)c).getID ()); list.setSelectedIndex (i); } else list.clearSelection (); } /** @return display name of the chooser */ public String getDisplayName() { return displayName; } /** No icon */ public Icon getSmallDisplayIcon() { return null; } /** No icon */ public Icon getLargeDisplayIcon() { return null; } /** ListSelectionListener interface implementation */ public void valueChanged(ListSelectionEvent e) { if (!list.isSelectionEmpty ()) { int i = list.getSelectedIndex (); getColorSelectionModel().setSelectedColor( new SuperColor (names [i], palette, colors [i])); } } public void setColor (final Color newColor) { getColorSelectionModel().setSelectedColor(newColor); } public Color getColor () { return getColorFromModel(); } /** Cell of the list showing palette colors */ final class MyListCellRenderer extends JPanel implements ListCellRenderer { protected Border hasFocusBorder = new LineBorder (UIManager.getColor ("List.focusCellHighlight")); // NOI18N protected Border noFocusBorder = new EmptyBorder(1, 1, 1, 1); boolean selected, hasFocus; int index; static final long serialVersionUID =-8877709520578055594L; /** Creates a new MyListCellRenderer */ public MyListCellRenderer () { setOpaque (true); setBorder (new EmptyBorder (1, 1, 1, 1)); } /** Overrides default preferredSize impl. * @return Standard method returned preferredSize * (depends on font size only). */ public Dimension getPreferredSize () { try { FontMetrics fontMetrics = getFontMetrics(getFont()); return new Dimension ( fontMetrics.stringWidth (names [index]) + 30, fontMetrics.getHeight () + 4 ); } catch (NullPointerException e) { return new Dimension (10, 10); } } public void paint (Graphics g) { Dimension rectangle = getSize (); Color color = g.getColor (); if (selected) g.setColor (UIManager.getColor ("List.selectionBackground")); // NOI18N else g.setColor (UIManager.getColor ("List.background")); // NOI18N g.fillRect (0, 0, rectangle.width - 1, rectangle.height - 1); if (hasFocus) { g.setColor (Color.black); g.drawRect (0, 0, rectangle.width - 1, rectangle.height - 1); } g.setColor (Color.black); g.drawRect (6, rectangle.height / 2 - 5 , 10, 10); g.setColor (colors [index]); g.fillRect (7, rectangle.height / 2 - 4 , 9, 9); if (selected) g.setColor (UIManager.getColor ("List.selectionForeground")); // NOI18N else g.setColor (UIManager.getColor ("List.foreground")); // NOI18N FontMetrics fm = g.getFontMetrics (); g.drawString (names [index], 22, (rectangle.height - fm.getHeight ()) / 2 + fm.getAscent ()); g.setColor (color); } /** This is the only method defined by ListCellRenderer. We just * reconfigure the Jlabel each time we're called. */ public java.awt.Component getListCellRendererComponent ( JList list, Object value, // value to display int index, // cell index boolean isSelected, // is the cell selected boolean cellHasFocus // the list and the cell have the focus ) { this.index = index; selected = isSelected; hasFocus = cellHasFocus; return this; } } } //-------------------------------------------------------------------------- // XMLPropertyEditor implementation public static final String XML_COLOR = "Color"; // NOI18N public static final String ATTR_TYPE = "type"; // NOI18N public static final String ATTR_RED = "red"; // NOI18N public static final String ATTR_GREEN = "green"; // NOI18N public static final String ATTR_BLUE = "blue"; // NOI18N public static final String ATTR_ID = "id"; // NOI18N public static final String ATTR_PALETTE = "palette"; // NOI18N public static final String VALUE_PALETTE = "palette"; // NOI18N public static final String VALUE_RGB = "rgb"; // NOI18N /** Called to load property value from specified XML subtree. If succesfully loaded, * the value should be available via the getValue method. * An IOException should be thrown when the value cannot be restored from the specified XML element * @param element the XML DOM element representing a subtree of XML from which the value should be loaded * @exception IOException thrown when the value cannot be restored from the specified XML element */ public void readFromXML (org.w3c.dom.Node element) throws java.io.IOException { if (!XML_COLOR.equals (element.getNodeName ())) { throw new java.io.IOException (); } org.w3c.dom.NamedNodeMap attributes = element.getAttributes (); try { String type = attributes.getNamedItem (ATTR_TYPE).getNodeValue (); String red = attributes.getNamedItem (ATTR_RED).getNodeValue (); String green = attributes.getNamedItem (ATTR_GREEN).getNodeValue (); String blue = attributes.getNamedItem (ATTR_BLUE).getNodeValue (); if (VALUE_PALETTE.equals (type)) { String id = attributes.getNamedItem (ATTR_ID).getNodeValue (); String palette = attributes.getNamedItem (ATTR_PALETTE).getNodeValue (); setValue (new SuperColor (id, Integer.parseInt (palette), new Color (Integer.parseInt (red, 16), Integer.parseInt (green, 16), Integer.parseInt (blue, 16)))); } else { setValue (new SuperColor (new Color (Integer.parseInt (red, 16), Integer.parseInt (green, 16), Integer.parseInt (blue, 16)))); } } catch (NullPointerException e) { throw new java.io.IOException (); } } /** Called to store current property value into XML subtree. The property value should be set using the * setValue method prior to calling this method. * @param doc The XML document to store the XML in - should be used for creating nodes only * @return the XML DOM element representing a subtree of XML from which the value should be loaded */ public org.w3c.dom.Node storeToXML(org.w3c.dom.Document doc) { org.w3c.dom.Element el = doc.createElement (XML_COLOR); el.setAttribute (ATTR_TYPE, (color.getID () == null) ? VALUE_RGB : VALUE_PALETTE); el.setAttribute (ATTR_RED, Integer.toHexString (color.getRed ())); el.setAttribute (ATTR_GREEN, Integer.toHexString (color.getGreen ())); el.setAttribute (ATTR_BLUE, Integer.toHexString (color.getBlue ())); if (color.getID () != null) { el.setAttribute (ATTR_ID, color.getID ()); el.setAttribute (ATTR_PALETTE, Integer.toString (color.getPalette ())); } return el; } } /* * Log * 22 Gandalf 1.21 1/13/00 Petr Jiricka i18n * 21 Gandalf 1.20 1/13/00 Petr Jiricka i18n * 20 Gandalf 1.19 12/8/99 Petr Nejedly Enabled setValue(null) * 19 Gandalf 1.18 11/26/99 Patrik Knakal * 18 Gandalf 1.17 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 17 Gandalf 1.16 8/9/99 Ian Formanek Generated Serial Version * UID * 16 Gandalf 1.15 7/30/99 Ian Formanek Fixed bug 2480 - Color * attribute can have haxedecimal values but int is expected. * 15 Gandalf 1.14 7/13/99 Ian Formanek Fixed readFromXML * 14 Gandalf 1.13 7/12/99 Ian Formanek Implements * XMLPropertyEditor * 13 Gandalf 1.12 7/8/99 Jesse Glick Context help. * 12 Gandalf 1.11 6/28/99 Ian Formanek throws * IllegalArgumentException if not passed Color instance in setValue * 11 Gandalf 1.10 6/27/99 Ian Formanek Ignores non-Color values * 10 Gandalf 1.9 6/8/99 Ian Formanek ---- Package Change To * org.openide ---- * 9 Gandalf 1.8 4/16/99 Libor Martinek * 8 Gandalf 1.7 3/4/99 Jan Jancura QuickSorter removed * 7 Gandalf 1.6 3/4/99 Jan Jancura bundle moved * 6 Gandalf 1.5 2/5/99 David Simonek * 5 Gandalf 1.4 2/5/99 Petr Hamernik bugfix * 4 Gandalf 1.3 2/4/99 David Simonek bugfix #1038 * 3 Gandalf 1.2 2/4/99 Petr Hamernik * 2 Gandalf 1.1 1/6/99 Ian Formanek some cotemporarily * commented out to compile under JDK 1.2 * 1 Gandalf 1.0 1/5/99 Ian Formanek * $ */